<?php
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Events\Event;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\User\Plugin;

class Security extends Plugin
{
    public function __construct($dependencyInjector)
    {
        $this->_dependencyInjector = $dependencyInjector;
    }

    /**
     * 如果找到了用户自定义的权限，则直接返回
     * 如果没有找到则先注册系统预置的权限，等跳转到主页的时候再动态的注册。
     *
     * @author liqiming
     * @date   2018-12-29
     * @return [type]     [description]
     */
    public function getAcl($uid = '', $role = '')
    {
        $di     = \Phalcon\Di::getDefault();
        $uidAcl = $di['redis']->get('uid:' . $uid . ':acl');
        if ($uidAcl) {
            return unserialize($uidAcl);
        } else {
            $userapp = $di['redis']->get('uid:' . $uid . ':app');
            if ($userapp) {
                $userapp = unserialize($userapp);
                $acl     = unserialize($di['redis']->get('base:acl'));
                if (!$acl) {
                    throw new Exception("获取系统权限异常", 1);
                }
                $file = file_get_contents(BASE_PATH . '/_app/config.json');
                $file = json_decode($file, true);
                foreach ($userapp as $key => $value) {
                    $acl->addResource(new Phalcon\Acl\Resource($value), $file[$value]['resource']);
                    foreach ($file[$value]['resource'] as $k => $val) {
                        $acl->allow($role, $value, $val);
                    }
                }
                $di['redis']->set('uid:' . $uid . ':acl', serialize($acl));
            }
        }
        $acl = $di['redis']->get('base:acl');
        if ($acl) {
            $acl = unserialize($acl);
        } else {
            $acl = new Phalcon\Acl\Adapter\Memory();
            $acl->setDefaultAction(Phalcon\Acl::DENY);
            $roles = [
                'user'      => new Role('user'), //用户角色是基础角色，虚拟的不能直接使用
                'guest'     => new Role('guest'),
                'designer'  => new Role('designer'),
                'editor'    => new Role('editor'),
                'seller'    => new Role('seller'),
                'responder' => new Role('responder'),
                'boss'      => new Role('boss'),
            ];
            $acl->addRole($roles['user']);
            $acl->addRole($roles['guest']);
            $acl->addRole($roles['designer'], $roles['user']);
            $acl->addRole($roles['editor'], $roles['user']);
            $acl->addRole($roles['seller'], $roles['user']);
            $acl->addRole($roles['responder'], $roles['user']);
            $acl->addRole($roles['boss'], $roles['user']);
            $AllResources = [
                //访客
                'guestResources'     => [
                    'index' => [
                        'readme',
                        'auth',
                        'signin',
                        'signup',
                        'error404',
                    ],
                ],
                //用户角色
                'userResources'      => [
                    'index' => [
                        'readme',
                        'index',
                        'editorupload',
                        'logout',
                        'error404',
                        'error',
                        'applist',
                        'installapp',
                    ],
                    'user'  => [
                        'profile',
                    ],
                ],
                //设计
                'designerResources'  => [
                    'index' => [
                        'designer',
                    ],
                ],
                //编辑
                'editorResources'    => [
                    'index' => [
                        'editor',
                    ],
                ],
                //销售
                'sellerResources'    => [
                    'index' => [
                        'seller',
                    ],
                ],
                //客服
                'responderResources' => [
                    'index' => [
                        'responder',
                    ],
                ],
                //老板
                'bossResources'      => [
                    'index' => [
                        'boss',
                    ],
                ],
            ];
            foreach ($roles as $role) {
                foreach ($AllResources[$role->getName() . 'Resources'] as $resource => $actions) {
                    $acl->addResource(new Phalcon\Acl\Resource($resource), $actions);
                    foreach ($actions as $action) {
                        $acl->allow($role->getName(), $resource, $action);
                    }
                }
            }
            $di['redis']->set('base:acl', serialize($acl));
        }

        return $acl;
    }

    public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
    {
        $controller = $dispatcher->getControllerName();
        $action     = $dispatcher->getActionName();

        $auth = null;
        if ($this->cookies->has('auth')) {
            $auth = $this->cookies->get('auth');
            $auth = unserialize($auth->getValue());
            $role = $auth['group'];
        } else {
            $role = 'guest';
            if (!in_array($action, ['auth', 'signin', 'signup', 'error404', 'readme'])) {
                $this->response->redirect("index/auth");
                return $this->response;
            }
        }
        $acl     = $this->getAcl($auth['id'], $role);
        $allowed = $acl->isAllowed($role, $controller, $action);
        if ($allowed != Acl::ALLOW) {
            $this->dispatcher->forward(array(
                "controller" => "index",
                "action"     => "error",
                "params"     => array('message' => '无权限访问！'),
            ));
            return false;
        }
    }
}
